#include "cxinoticebox_p.h"
#include <QApplication>
#include <QLayout>
#include <QScreen>
#include <algorithm>
#include <utility>
CxiNoticeBoxPrivate::CxiNoticeBoxPrivate(CxiNoticeBox* p)
	: q_ptr(p),
	  m_maxVisibleCount(3),
	  m_allowShowNewMsg(true)
{
}
CxiNoticeBoxPrivate::~CxiNoticeBoxPrivate()
{
	// 清理所有消息窗口
	qDeleteAll(m_noticeList);
	m_noticeList.clear();
}
void CxiNoticeBoxPrivate::init()
{
	Q_Q(CxiNoticeBox);
}
void CxiNoticeBoxPrivate::addNoticeWidget(const NoticeData& data)
{
	CxiNoticeWidget* widget = new CxiNoticeWidget(data);
	// 连接窗口信号到私有类槽函数
	connect(widget, &CxiNoticeWidget::needRemove,
			this, &CxiNoticeBoxPrivate::removeNotice);
	// MQ单击事件连接
	connect(widget, &CxiNoticeWidget::mqClicked,
			this, [widget](const QVariant& mqData) {
				// 触发MQ单击回调
				NoticeData data = widget->getData();
				if (data.mqClickCallback)
				{
					data.mqClickCallback(mqData);
				}
			});

	// MQ双击事件连接
	connect(widget, &CxiNoticeWidget::mqDoubleClicked,
			this, [widget](const QVariant& mqData) {
				// 触发MQ双击回调
				NoticeData data = widget->getData();
				if (data.mqDoubleClickCallback)
				{
					data.mqDoubleClickCallback(mqData);
				}
			});
	// 确认按钮点击事件连接
	connect(widget, &CxiNoticeWidget::confirmClicked,
			this, [widget]() {
				// 触发确认回调
				NoticeData data = widget->getData();
				if (data.confirmCallback)
				{
					data.confirmCallback();
				}
			});
	m_noticeList.append(widget);
	showNotices();
}
void CxiNoticeBoxPrivate::showNotices()
{
	// 不允许显示新消息
	if (!m_allowShowNewMsg)
	{
		for (auto i: m_noticeList)
		{
			if (i->isVisible())
			{
				i->hide();
			}
		}
		return;
	}
	// 展示消息
	if (!m_noticeList.isEmpty())
	{
		rearrangeNotices();
		//展示列表中前n个窗口
		int totalOffsetY = 0;
		QRect screenRect = QApplication::primaryScreen()->availableGeometry();
		QPoint bottomRightPos = screenRect.bottomRight();
		for (int i = 0; i < qMin(m_maxVisibleCount, m_noticeList.size()); ++i)
		{
			CxiNoticeWidget* notice = m_noticeList.at(i);
			if (notice->layout())
			{
				notice->layout()->activate();// 强制布局更新
			}
			notice->adjustSize();// 确保尺寸是自适应后的真实值
			QPoint noticePos(
					bottomRightPos.x() - notice->size().width(),
					bottomRightPos.y() - totalOffsetY - notice->size().height());
			// 设置窗口位置和尺寸
			notice->geometry();
			notice->setGeometry(QRect(noticePos, notice->size()));
			if (notice->isHidden())
			{
				notice->show();
			}
			totalOffsetY += notice->size().height() + 5;
		}
		//隐藏后续窗口
		for (int i = qMin(m_maxVisibleCount, m_noticeList.size()); i < m_noticeList.size(); ++i)
		{
			if (m_noticeList.at(i) && m_noticeList.at(i)->isVisible())
			{
				m_noticeList.at(i)->hide();
			}
		}
	}
}
void CxiNoticeBoxPrivate::removeNotice(CxiNoticeWidget* widget)
{
	if (!widget || !m_noticeList.contains(widget)) return;
	// 断开连接并从列表中移除
	disconnect(widget, nullptr, this, nullptr);
	m_noticeList.removeOne(widget);
	//重新展示
	showNotices();
	// 销毁窗口
	widget->deleteLater();
}

void CxiNoticeBoxPrivate::rearrangeNotices()
{
	// 重新排列消息位置
	// 对 m_noticeList 进行自定义排序
	std::sort(m_noticeList.begin(), m_noticeList.end(),
			  [](CxiNoticeWidget* a, CxiNoticeWidget* b) {
				  // 先比较优先级：优先级越高，排序越靠前
				  // 假设 NoticeLevel 是枚举，值越大优先级越高（如 Level3 > Level2 > Level1）
				  if (a->data().level != b->data().level)
				  {
					  return a->getData().level > b->getData().level;
				  }
				  // 若优先级相同：后创建的窗口（时间戳更大）排在前面
				  else
				  {
					  return a->timestamp() > b->timestamp();
				  }
			  });
}
void CxiNoticeBoxPrivate::removeAllNotices()
{
	foreach (CxiNoticeWidget* widget, m_noticeList)
	{
		if (widget)
		{
			widget->deleteLater();
		}
	}
	m_noticeList.clear();
}
void CxiNoticeBoxPrivate::addNotice(const QString& text, int autoPopDelay, const QString& caption, NoticeType type)
{
	NoticeData noticeData;
	noticeData.text = text;
	noticeData.caption = caption;
	noticeData.type = type;
	noticeData.autoPopDelay = autoPopDelay;
	addNoticeWidget(noticeData);
}
void CxiNoticeBoxPrivate::addConfirm(const QString& text, std::function<void()> confirmCallback, int autoPopDelay, const QString& caption, const QString& btnText)
{
	NoticeData noticeData;
	noticeData.text = text;
	noticeData.caption = caption;
	noticeData.type = NoticeType::Confirm;
	noticeData.autoPopDelay = autoPopDelay;
	noticeData.isConfirmBox = true;
	noticeData.confirmCallback = std::move(confirmCallback);
	noticeData.confirmBtnText = btnText;
	addNoticeWidget(noticeData);
}
void CxiNoticeBoxPrivate::addMQ(const QVariant& mqData, std::function<void(const QVariant&)> mqClickCallback, std::function<void(const QVariant&)> mqDoubleClickCallback, int autoPopDelay, const QString& caption)
{
	NoticeData noticeData;
	noticeData.text = "MQ消息";
	noticeData.caption = caption;
	noticeData.type = NoticeType::MQ;
	noticeData.autoPopDelay = autoPopDelay;
	noticeData.isMQ = true;
	noticeData.mqData = mqData;
	noticeData.mqClickCallback = std::move(mqClickCallback);
	noticeData.mqDoubleClickCallback = std::move(mqDoubleClickCallback);
	addNoticeWidget(noticeData);
}
